{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:23:39.033272Z",
     "start_time": "2025-03-10T16:23:34.240990Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n",
    "\n",
    "seed = 42\n",
    "torch.manual_seed(seed)\n",
    "torch.cuda.manual_seed_all(seed)\n",
    "np.random.seed(seed)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=9, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.1\n",
      "numpy 2.0.1\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu126\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 准备数据\n",
    "\n",
    "这里使用subword分词，我们使用已经清洗好的数据集，可以从[此处](https://www.kaggleusercontent.com/kf/98352223/eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..nKt8lrIW5ej5QJQVpOWuqQ.oLIgiLMONU5Gpj_maVudRJa55NSOCILxk4JNZhvuXmeDBR-oG0uQm7bDHBfSwZRGvOBHQTsRV308iNP80btfwMinQ7yvJNt-GwdQF4XR4DIsg-2CbEPYiMsi_NdbL0FmE9LYStKdxCWbrCZCCMrTmo5LxR1txwibXaSpeP5Inobhbez5zetZIRH210CBuX2JbpRc_DULQpazKbtFPitwyfktVmdG_syvVAU6Sk9b0r0_erYAgb_jkKXX1Mxo1KzWSKLcAvbmMIPcsUkx9PmeJDs_wopfsQsZ1h5jaQX4_l0CTZrEenP6lIPDxpTwXANqqdHspmZeeEIAThqCHC6sb5DxTvG89BwzY9rc53Aa0uX4V806wJVybnRXoaV65K4GqpjnxbBK0WC8G-2lNtrqFujE89KDXZjFPgyfOEj1QIu13oFNSjgs6o4VV1PdZOrhiNdSmjb44c22l_unOaFojzJgzcPxq9AG2lcmrOpdZ2qu1jjdwey-58TA2ZHNCo3XnjEe2n3ignpnbsdLFpo22O8QakSUHv91wuYDYdNi3AiSmltL_k2ChuKfJ0G8kATpLe4k8wA26sO4GMXg4HImOr3b4aDVEIWXdApHP0ecFKs6ELTo8O7X-TK8Jvbua7e6qpDfDc-r_cD73fVSgSek5yNmKQMBzuVcjkprXmcxICQ.kV1b4N1s64NERKnt4zwQgQ/imdb_processed.csv)下载，分词使用 [subword-nmt](https://github.com/rsennrich/subword-nmt)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:23:39.593885Z",
     "start_time": "2025-03-10T16:23:39.034266Z"
    }
   },
   "source": [
    "cleaned_df = pd.read_csv(\"imdb_processed.csv\")\n",
    "print(cleaned_df.shape) # (50000, 2), 50000条评论, 2列\n",
    "\n",
    "# 随机打乱数据，取训练集和测试集\n",
    "np.random.seed(seed) #随机\n",
    "cleaned_df = cleaned_df.sample(frac=1).reset_index(drop=True)#打乱，frac=1表示全部打乱（frac是比例，reset_index(drop=True)是重新索引\n",
    "with open(\"imdb_train.txt\", \"w\", encoding=\"utf8\") as file:# 保存训练集\n",
    "    for line in cleaned_df.processed.values[:25000]:#只保存了processed列，即评论文本，没有保存label列\n",
    "        file.write(line.lower() + \"\\n\") #变为小写，token数量少一些\n",
    "\n",
    "with open(\"imdb_test.txt\", \"w\", encoding=\"utf8\") as file:# 保存测试集\n",
    "    for line in cleaned_df.processed.values[25000:]:\n",
    "        file.write(line.lower() + \"\\n\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(50000, 2)\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:23:39.598100Z",
     "start_time": "2025-03-10T16:23:39.594884Z"
    }
   },
   "source": "# !pip install subword-nmt  ",
   "outputs": [],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:04.097413Z",
     "start_time": "2025-03-10T16:23:39.599097Z"
    }
   },
   "source": [
    "# 学习bpe分词(很慢,学一次就好)\n",
    "# -i 选择学习的文件\n",
    "# -o 核心输出文件,分词需要用到imdb_bpe_code,生成的 imdb_bpe_code 文件包含了学习到的 BPE 操作规则。这些规则用于将单词分割成子词单元\n",
    "# --write-vocabulary 字典输出文件，imdb_bpe_vocab 文件包含了根据 BPE 规则生成的词汇表，列出了所有子词单元及其频率\n",
    "# -s 词表大小\n",
    "!subword-nmt learn-joint-bpe-and-vocab -i ./imdb_train.txt -o ./imdb_bpe_code --write-vocabulary ./imdb_bpe_vocab -s 8000\n",
    "\n",
    "\n"
   ],
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n",
      "  0%|          | 0/8000 [00:00<?, ?it/s]\n",
      "  0%|          | 1/8000 [00:00<14:26,  9.24it/s]\n",
      "  0%|          | 5/8000 [00:00<05:28, 24.35it/s]\n",
      "  0%|          | 8/8000 [00:00<05:23, 24.68it/s]\n",
      "  0%|          | 11/8000 [00:00<05:07, 25.96it/s]\n",
      "  0%|          | 16/8000 [00:00<03:59, 33.29it/s]\n",
      "  0%|          | 21/8000 [00:00<03:31, 37.67it/s]\n",
      "  0%|          | 29/8000 [00:00<02:41, 49.39it/s]\n",
      "  0%|          | 37/8000 [00:00<02:30, 52.95it/s]\n",
      "  1%|          | 53/8000 [00:01<01:38, 80.52it/s]\n",
      "  1%|          | 64/8000 [00:01<01:30, 87.21it/s]\n",
      "  1%|          | 78/8000 [00:01<01:18, 100.46it/s]\n",
      "  1%|1         | 95/8000 [00:01<01:05, 120.14it/s]\n",
      "  1%|1         | 113/8000 [00:01<00:57, 136.51it/s]\n",
      "  2%|1         | 133/8000 [00:01<00:51, 153.27it/s]\n",
      "  2%|1         | 158/8000 [00:01<00:43, 180.91it/s]\n",
      "  2%|2         | 179/8000 [00:01<00:41, 186.45it/s]\n",
      "  3%|2         | 201/8000 [00:01<00:40, 192.45it/s]\n",
      "  3%|2         | 236/8000 [00:01<00:32, 236.25it/s]\n",
      "  3%|3         | 262/8000 [00:02<00:32, 240.93it/s]\n",
      "  4%|3         | 287/8000 [00:02<00:31, 241.60it/s]\n",
      "  4%|3         | 314/8000 [00:02<00:30, 248.70it/s]\n",
      "  4%|4         | 351/8000 [00:02<00:27, 282.59it/s]\n",
      "  5%|4         | 380/8000 [00:02<00:27, 275.09it/s]\n",
      "  5%|5         | 408/8000 [00:02<00:27, 276.40it/s]\n",
      "  6%|5         | 447/8000 [00:02<00:24, 308.78it/s]\n",
      "  6%|6         | 483/8000 [00:02<00:23, 319.94it/s]\n",
      "  7%|6         | 528/8000 [00:02<00:20, 357.73it/s]\n",
      "  7%|7         | 568/8000 [00:02<00:20, 368.35it/s]\n",
      "  8%|7         | 605/8000 [00:03<00:22, 334.33it/s]\n",
      "  8%|8         | 654/8000 [00:03<00:19, 376.89it/s]\n",
      "  9%|8         | 693/8000 [00:03<00:20, 364.40it/s]\n",
      "  9%|9         | 738/8000 [00:03<00:18, 387.40it/s]\n",
      " 10%|9         | 778/8000 [00:03<00:18, 390.17it/s]\n",
      " 10%|#         | 818/8000 [00:03<00:19, 362.94it/s]\n",
      " 11%|#         | 867/8000 [00:03<00:17, 397.65it/s]\n",
      " 11%|#1        | 911/8000 [00:03<00:17, 409.33it/s]\n",
      " 12%|#2        | 965/8000 [00:03<00:15, 445.61it/s]\n",
      " 13%|#2        | 1011/8000 [00:04<00:15, 438.67it/s]\n",
      " 13%|#3        | 1072/8000 [00:04<00:14, 486.28it/s]\n",
      " 14%|#4        | 1122/8000 [00:04<00:14, 484.90it/s]\n",
      " 15%|#4        | 1172/8000 [00:04<00:13, 489.13it/s]\n",
      " 15%|#5        | 1225/8000 [00:04<00:13, 498.60it/s]\n",
      " 16%|#6        | 1285/8000 [00:04<00:12, 526.49it/s]\n",
      " 17%|#6        | 1338/8000 [00:04<00:12, 523.60it/s]\n",
      " 17%|#7        | 1391/8000 [00:04<00:13, 503.51it/s]\n",
      " 18%|#8        | 1442/8000 [00:04<00:13, 502.09it/s]\n",
      " 19%|#8        | 1493/8000 [00:05<00:13, 489.16it/s]\n",
      " 19%|#9        | 1543/8000 [00:05<00:13, 468.47it/s]\n",
      " 20%|#9        | 1591/8000 [00:05<00:14, 450.55it/s]\n",
      " 21%|##        | 1645/8000 [00:05<00:13, 471.66it/s]\n",
      " 21%|##1       | 1693/8000 [00:05<00:13, 455.14it/s]\n",
      " 22%|##2       | 1768/8000 [00:05<00:11, 534.68it/s]\n",
      " 23%|##2       | 1835/8000 [00:05<00:10, 571.63it/s]\n",
      " 24%|##3       | 1893/8000 [00:05<00:10, 558.05it/s]\n",
      " 24%|##4       | 1959/8000 [00:05<00:10, 586.75it/s]\n",
      " 25%|##5       | 2022/8000 [00:05<00:09, 597.94it/s]\n",
      " 26%|##6       | 2104/8000 [00:06<00:08, 662.04it/s]\n",
      " 27%|##7       | 2192/8000 [00:06<00:08, 724.50it/s]\n",
      " 28%|##8       | 2278/8000 [00:06<00:07, 764.44it/s]\n",
      " 30%|##9       | 2369/8000 [00:06<00:06, 805.52it/s]\n",
      " 31%|###       | 2450/8000 [00:06<00:06, 803.76it/s]\n",
      " 32%|###1      | 2549/8000 [00:06<00:06, 857.01it/s]\n",
      " 33%|###3      | 2644/8000 [00:06<00:06, 884.58it/s]\n",
      " 34%|###4      | 2733/8000 [00:06<00:06, 848.87it/s]\n",
      " 36%|###5      | 2845/8000 [00:06<00:05, 925.77it/s]\n",
      " 37%|###6      | 2951/8000 [00:06<00:05, 964.32it/s]\n",
      " 38%|###8      | 3074/8000 [00:07<00:04, 1041.79it/s]\n",
      " 40%|###9      | 3195/8000 [00:07<00:04, 1090.71it/s]\n",
      " 42%|####1     | 3331/8000 [00:07<00:03, 1168.30it/s]\n",
      " 43%|####3     | 3479/8000 [00:07<00:03, 1257.37it/s]\n",
      " 46%|####5     | 3643/8000 [00:07<00:03, 1368.39it/s]\n",
      " 47%|####7     | 3785/8000 [00:07<00:03, 1382.19it/s]\n",
      " 50%|####9     | 3988/8000 [00:07<00:02, 1572.28it/s]\n",
      " 53%|#####2    | 4204/8000 [00:07<00:02, 1745.94it/s]\n",
      " 56%|#####5    | 4477/8000 [00:07<00:01, 2038.26it/s]\n",
      " 59%|#####8    | 4681/8000 [00:08<00:03, 1052.75it/s]\n",
      " 60%|######    | 4839/8000 [00:08<00:03, 811.64it/s] \n",
      " 62%|######2   | 4964/8000 [00:08<00:04, 757.44it/s]\n",
      " 63%|######3   | 5070/8000 [00:09<00:03, 734.68it/s]\n",
      " 65%|######4   | 5164/8000 [00:09<00:03, 711.11it/s]\n",
      " 66%|######5   | 5249/8000 [00:09<00:04, 685.86it/s]\n",
      " 67%|######6   | 5327/8000 [00:09<00:03, 682.71it/s]\n",
      " 68%|######7   | 5402/8000 [00:09<00:03, 674.41it/s]\n",
      " 69%|######8   | 5482/8000 [00:09<00:03, 701.94it/s]\n",
      " 69%|######9   | 5556/8000 [00:09<00:03, 708.98it/s]\n",
      " 70%|#######   | 5635/8000 [00:09<00:03, 729.47it/s]\n",
      " 71%|#######1  | 5711/8000 [00:09<00:03, 733.02it/s]\n",
      " 72%|#######2  | 5786/8000 [00:10<00:03, 714.90it/s]\n",
      " 73%|#######3  | 5861/8000 [00:10<00:02, 723.12it/s]\n",
      " 74%|#######4  | 5935/8000 [00:10<00:02, 689.40it/s]\n",
      " 75%|#######5  | 6008/8000 [00:10<00:02, 694.66it/s]\n",
      " 76%|#######6  | 6092/8000 [00:10<00:02, 735.25it/s]\n",
      " 77%|#######7  | 6187/8000 [00:10<00:02, 796.33it/s]\n",
      " 79%|#######8  | 6289/8000 [00:10<00:01, 859.12it/s]\n",
      " 80%|#######9  | 6384/8000 [00:10<00:01, 880.90it/s]\n",
      " 81%|########  | 6473/8000 [00:10<00:01, 803.02it/s]\n",
      " 82%|########1 | 6555/8000 [00:11<00:01, 753.24it/s]\n",
      " 83%|########3 | 6652/8000 [00:11<00:01, 809.87it/s]\n",
      " 84%|########4 | 6741/8000 [00:11<00:01, 830.15it/s]\n",
      " 85%|########5 | 6832/8000 [00:11<00:01, 851.11it/s]\n",
      " 87%|########6 | 6941/8000 [00:11<00:01, 919.16it/s]\n",
      " 88%|########8 | 7061/8000 [00:11<00:00, 998.09it/s]\n",
      " 90%|########9 | 7171/8000 [00:11<00:00, 1025.05it/s]\n",
      " 91%|######### | 7279/8000 [00:11<00:00, 1041.11it/s]\n",
      " 93%|#########2| 7422/8000 [00:11<00:00, 1155.31it/s]\n",
      " 95%|#########4| 7580/8000 [00:11<00:00, 1278.28it/s]\n",
      " 97%|#########6| 7754/8000 [00:12<00:00, 1412.34it/s]\n",
      " 99%|#########8| 7901/8000 [00:12<00:00, 1242.16it/s]\n",
      "100%|##########| 8000/8000 [00:12<00:00, 652.95it/s] \n"
     ]
    }
   ],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "source": [
    "# 应用bpe分词,-c 指定 BPE 编码的配置文件,就是上面生成的 imdb_bpe_code 文件\n",
    "!subword-nmt apply-bpe -c ./imdb_bpe_code -i ./imdb_train.txt -o ./imdb_train_bpe.txt\n",
    "!subword-nmt apply-bpe -c ./imdb_bpe_code -i ./imdb_test.txt -o ./imdb_test_bpe.txt"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:18.290204Z",
     "start_time": "2025-03-10T16:24:04.099401Z"
    }
   },
   "outputs": [],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:18.459710Z",
     "start_time": "2025-03-10T16:24:18.291200Z"
    }
   },
   "source": [
    "# 分词后的数据长什么样,与分词前imdb_train.txt进行对比来理解，@@ 是分词的标记，如果一个单词被分开，就会加上@@\n",
    "!head ./imdb_train_bpe.txt\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i really liked sum@@ mer@@ sla@@ m due look a@@ ren@@ a , cur@@ tain look overall interesting reason . anyways , could one best sum@@ mer@@ sla@@ m ever w@@ w@@ f le@@ x lu@@ ger main event yo@@ ko@@ z@@ un@@ a , time ok huge fat man v strong man i glad time changed . it terrible main event like every match lu@@ ger terrible . other match card ra@@ z@@ or ra@@ mon v ted di@@ bi@@ ase , ste@@ in@@ er brothers v hea@@ ven@@ ly bo@@ dies , sha@@ wn micha@@ els v cur@@ t h@@ ening , event sha@@ wn named big monster body guard die@@ sel , irs v - - kid , bre@@ t hart first take do@@ ink take jerry law@@ ler stuff har@@ ts law@@ ler always interesting , lu@@ d@@ vi@@ g bor@@ ga destroyed marty jan@@ ne@@ tty , under@@ taker took giant gon@@ z@@ ale@@ z another terrible match , the smoking g@@ unn@@ s tat@@ an@@ ka took ba@@ m ba@@ m bi@@ ge@@ low head@@ shr@@ in@@ kers , yo@@ ko@@ z@@ un@@ a def@@ ended world title le@@ x lu@@ ger match boring terrible ending . however deserves\n",
      "not many television show appeal quite many different kind fan like far@@ scape . . . i know youn@@ g@@ ster year old fan male female many different country think ad@@ ore t . v miniseries . it element found almost every show t . v , character driven drama could australian soap opera yet episode science fact fiction would give even har@@ di@@ est tre@@ k@@ kie run money brain@@ ben@@ der sta@@ ke ! wor@@ m@@ hole theory , time travel true equ@@ a@@ tional form . . . magnificent . it embr@@ ace culture ma@@ p possibility endless multiple star therefore thousand planet choose . with broad scope would expected nothing would able keep illu@@ sion long , far@@ scape really come element . . . it succeeds others failed , especially like star trek universe practically zero ka@@ os element ! they ran idea pretty quickly kept re@@ ha@@ shing ! over course season manage keep audience attention using good continuity constant character evol@@ ution multiple thread every episode unique personal touch camera specific certain character group within whole . this structure allows extremely large area subject matter loy@@ alty for@@ ged broken many way many many issue . i happened see pilot premiere passing keep tun@@ ing see cri@@ ch@@ ton would ever get girl , seeing television i deli@@ ghted see available dvd i admit thing kept s@@ ane whilst i hour night shift developed chron@@ ic in@@ som@@ nia . . . far@@ scape thing get extremely long night . . . do fav@@ our watch pilot see i mean . . . far@@ scape com@@ et\n",
      "the film quickly get major chase scene ever increa@@ sing destruction . the first really bad thing guy hi@@ jac@@ king steven seagal would beaten pulp seagal driving , probably would ended whole premise movie . it seems like decided make kind change movie plot , plan enjoy action , expect coherent plot . turn sense logic may , re@@ duce chance getting head@@ ache . i give hope steven seagal trying move back towards type character portrayed popular movie .\n",
      "jane austen would definitely appro@@ ve one ! g@@ wy@@ ne@@ th pal@@ tro@@ w awesome job capturing attitude emma . she funny without exce@@ ssively silly , yet eleg@@ ant . she put convincing british accent british , maybe i best judge , fooled . . . also excellent sli@@ ding do@@ ors . . . i sometimes forget american ! . also brilliant jeremy north@@ am sophi@@ e th@@ omp@@ son ph@@ y@@ lli@@ da law emma th@@ omp@@ son sister mother bates woman . they nearly steal show . . . ms . law even line ! highly recommended .\n",
      "expec@@ ta@@ tions somewhat high i went see movie , i thought steve care@@ ll could wrong coming great movie like an@@ chor@@ man , the year - old virgin , little miss sun@@ shine . boy , i wrong . i start right movie certain point steve care@@ ll allowed steve care@@ ll . there handful moment film made laugh , due almost entirely given wi@@ ggle - room thing . he undoubtedly talented individual , shame sig@@ ned turned , opinion , total train - wreck . with way , i discus went horri@@ f@@ y@@ ingly wrong . the film begin dan burns , wi@@ do@@ wer three girl considered na@@ tionally syn@@ di@@ cated advice colum@@ n . he pre@@ pa@@ res girl family reunion , extended relative ga@@ ther time . the family high at@@ op list thing make awful movie . no family beha@@ ves like . it almost tran@@ spor@@ ted pleasan@@ t@@ ville leave bea@@ ver . they caricature think family . it reach point become obnoxious simply frustrating . touch football , cro@@ ss@@ word puzzle competition , family bow@@ ling , talent show are not how actual people behave . it almost sick@@ ening . another big flaw woman care@@ ll supposed falling . obser@@ ving first scene steve care@@ ll like watching stro@@ ke victim trying re@@ hab@@ il@@ it@@ ated . what i imagine supposed unique original woman come mildly retarded . it make think movie taking place another planet . i left theater wondering i saw . after thinking , i think much .\n",
      "i watched movie fairly regular basis life , never get old . for sni@@ de remark insult mostly david spa@@ de , tommy boy giant heart . and keep movie funny year . tommy cal@@ la@@ han chris far@@ ley son big tom cal@@ la@@ han brian den@@ ne@@ h@@ y , master car part sal@@ es@@ man , ri@@ dden life . but died dy wedding day , tommy learns company deb@@ t , bought ray z@@ al@@ in@@ sky dan ak@@ roy@@ d , owner huge car part company . so order save company , tommy go road sell company new bra@@ ke pa@@ d . along ride , though choice , richard hay@@ den david spa@@ de former cla@@ ss@@ mate tommy big tom right - hand man . the movie ride chemistry two sn@@ l star real - life best friend chris far@@ ley david spa@@ de . the duo enough comic energy going power world . it big , dumb guy versus smart little guy . it work , scene un@@ forget@@ tably funny . far@@ ley spa@@ de actually decent dramatic actor well . although film primarily comedy , fair share drama , spa@@ de especially far@@ ley good making audience laugh . forgive , i talk chris far@@ ley little . i read biography the chris far@@ ley show a biography three acts , anyone care , understanding chris real life made movie special . chris far@@ ley genuinely good person strugg@@ led , ultimately failed con@@ qu@@ er addic@@ tion . although first movie major role , best film . it really showed , much talent . knowing chris story add another layer movie , although make le funny . far@@ ley spa@@ de matched good screen cast . rob lo@@ we suit@@ ably sli@@ my tommy new brother , bo derek solid step - mother . brian den@@ ne@@ h@@ y great big tom . den@@ ne@@ h@@ y make easy believe father son . big tom crazy son , although smar@@ ter mature . dan ak@@ roy@@ d give one best performance z@@ al@@ in@@ sky , giving tommy hard truth behind advertising . julie warner also good tommy love interest , michelle . for , peter se@@ gal one great comedy director . he keep pace quick ener@@ ge@@ tic , importantly , know make comedy funny . he be@@ la@@ bor joke , understand@@ s funny actor know allows . but se@@ gal go step . he give tommy boy friendly , almost nostal@@ gic tone tu@@ g heart@@ str@@ ings genuinely ti@@ ckle f@@ unn@@ y@@ bone . cri@@ tics like tommy boy . shame . a movie super sophisticated sub@@ ver@@ sively intellectual funny god for@@ bid far@@ ley spa@@ de forced mu@@ ted comedy la the office . this great movie one - time favorite .\n",
      "for story hope high@@ ligh@@ ted tragic reality youth face . fav@@ ela rising draw one scary , un@@ safe un@@ fair world show beautiful color moving music one man dedicated friend choose accept world change action art . an entertaining , interesting , emotional , aes@@ the@@ tically beautiful film . i showed film numerous high school student well live neighborhood poverty gun violence en@@ amo@@ red anderson , protagonist . i recommend film age due subtitle image death background .\n",
      "okay , i get pur@@ gatory thing first time i watched episode . it seemed like something significant going i put finger . this time co@@ sta me@@ sa fire tv really caught attention - helped i writing ess@@ ay inf@@ er@@ no ! but let see ha@@ s@@ n t discu@@ ssed yet . . . a tw@@ op review mentioned tony flight sta@@ ir go broken elev@@ ator . yeah , significant number lot reason , especially religious , one ya . on hun@@ ch i con@@ sulted wi@@ ki@@ pe@@ dia , guess dan@@ te divi@@ ded level ? pur@@ g@@ at@@ ori@@ o . exclu@@ ding ante - pur@@ gatory para@@ di@@ se . the stuff bottom sta@@ ir . . . tony get . on alle@@ ge@@ dly random mon@@ k - slap scene . as soon mon@@ k appeared , fit perfectly place tony trying get pur@@ gatory . you tell got worried christian commercial death , disease , sin came , getting desperate christian heaven looking kinda i@@ ffy . by time meet mon@@ k thinking hey maybe guy help ? sound like contem@@ pla@@ ting religion e . g . bud@@ d@@ h@@ ism wondering path could take sal@@ vation . not tony necessarily literally thinking becoming bud@@ d@@ hi@@ st , appears fin@@ ner@@ ty tried me@@ ssed . that slap face basically tell tony quick fix - , , suddenly embr@@ ace bud@@ d@@ h@@ ism get . tony initially concerned getting heaven . but con@@ ference en@@ tr@@ ance , realizes going easy . at first i saw name v . driver li@@ cen@@ se problem tony led sort double life , killing people sleeping around kept secret people . he feel free affair qu@@ as@@ i - mel@@ fi kevin fin@@ ner@@ ty . he figure can fool people k@@ f card , like hotel rec@@ ep@@ tion@@ ist , get pur@@ gatory . those helicopter - helicopter heaven ? - keeping track everything . after reading theory in@@ fin@@ ner@@ ty , though , seems like k@@ f identity remin@@ der in@@ fin@@ ite different path tony could taken life . possibly along car joke involving in@@ fin@@ it@@ i made sense otherwise . a@@ a@@ and point brain fi@@ zz@@ le .\n",
      "i disappointed series . it lot cool graphic . the level detail went minimal , i always got feeling audience pat@@ ron@@ ized - - lot seemed this extremely cool going explain detail get anyway . let show pretty picture entertain . the host would drop interesting - sounding word spar@@ tic@@ les super - sym@@ me@@ try without attempt explaining . we look wi@@ ki@@ pe@@ dia . furthermore , i know quite bit super@@ string la@@ y@@ man i found explanation convoluted could much better . they could chosen much better example explain concept , instead , example used confusing ob@@ scu@@ red subject . ad@@ di@@ tionally , i got sick repeti@@ ti@@ veness . they could easily con@@ den@@ sed series one episode cut repeti@@ tion . they must shown clip qu@@ an@@ tum ca@@ f time . the host kept saying thing . i remember many time said the universe made tiny little vi@@ bra@@ ting string . it like trying brain@@ wa@@ sh u accep@@ ting super@@ string best thing since sli@@ ced b@@ read . finally , show ended unpleasant sense competition fer@@ mil@@ a@@ b cer@@ n , clearly bi@@ ased towards fer@@ mil@@ a@@ b . this supposed edu@@ cational program qu@@ an@@ tum physi@@ c , whether us better europe vice ver@@ sa ! i also felt part pat@@ ron@@ i@@ zing - - audi@@ en@@ ces need see conflict remain interested . please . give little credit . overall , thumb -\n",
      "the first minute tin@@ sel@@ town finger te@@ e@@ tering remote , po@@ ised flick around watch something else . the premise two writer , luck , living self - stor@@ age - space bin mildly amusing , , painfully bland . the introduction character , played joe pan@@ to@@ li@@ ano - big deal movie guy , life park sleep la@@ v@@ atory , offered hope i decided give minute . and kri@@ sty s@@ wan@@ sons introduction bud@@ ding film director bor@@ der@@ line ny@@ mp@@ hom@@ ani@@ ac , added bit sp@@ ice . her solid acting performance raised presence beyond welcome eye - candy inclu@@ sion . ultimately , obvious low - budget impact film poorly shot scene , stu@@ t@@ tured pace slapstick hand@@ ling certain moment . some favourite movie time low budget , whi@@ th@@ nail i one also deal guy dream , luck . however , money , actor save tin@@ sel@@ town terrible movie archi@@ ve nu@@ dge could cult movie archi@@ ve . i laughed loud scene involving joe pan@@ to@@ li@@ ano character . in particular , pen@@ ultimate scene terribly clichd , still funny , rich - - scre@@ wed - character house , story un@@ ra@@ vel@@ s towards final moment . i see tin@@ sel@@ town great stage play film - maker best transla@@ te celluloid , simply work i laughed loud scene one liner , i think first minute du@@ lled sen@@ s expectation degree i would laughed anything . unless stuck no@@ vel@@ ty coffee coa@@ ster , pick see bar@@ gain bu@@ cket .\n"
     ]
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "source": [
    "cleaned_df.head()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:18.477096Z",
     "start_time": "2025-03-10T16:24:18.460703Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "                                           processed  label\n",
       "0  I really liked Summerslam due look arena , cur...      1\n",
       "1  Not many television show appeal quite many dif...      1\n",
       "2  The film quickly get major chase scene ever in...      0\n",
       "3  Jane Austen would definitely approve one ! Gwy...      1\n",
       "4  Expectations somewhat high I went see movie , ...      0"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>processed</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>I really liked Summerslam due look arena , cur...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Not many television show appeal quite many dif...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>The film quickly get major chase scene ever in...</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Jane Austen would definitely approve one ! Gwy...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Expectations somewhat high I went see movie , ...</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:20.935989Z",
     "start_time": "2025-03-10T16:24:18.478087Z"
    }
   },
   "source": [
    "subwords = [] # 保存分词后的结果\n",
    "with open(\"imdb_train_bpe.txt\", \"r\", encoding=\"utf8\") as file:\n",
    "    for line in file.readlines():\n",
    "        subwords.append(line.strip())\n",
    "        \n",
    "with open(\"imdb_test_bpe.txt\", \"r\", encoding=\"utf8\") as file:\n",
    "    for line in file.readlines():\n",
    "        subwords.append(line.strip())\n",
    "        \n",
    "cleaned_df[\"subwords10k\"] = subwords # 保存分词后的结果\n",
    "cleaned_df[\"split\"] = [\"train\"] * 25000 + [\"test\"] * 25000 # 标记训练集和测试集\n",
    "cleaned_df.to_csv(\"imdb_subwords.csv\", index=False) #把分词后的结果保存到csv文件"
   ],
   "outputs": [],
   "execution_count": 8
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:22.803735Z",
     "start_time": "2025-03-10T16:24:20.936985Z"
    }
   },
   "source": [
    "from torch.utils.data import Dataset, DataLoader\n",
    "\n",
    "# 随后加载数据集就从bpe分词的文件里加载\n",
    "class IMDBDataset(Dataset):\n",
    "    def __init__(self, mode=\"train\"):\n",
    "        df = pd.read_csv(\"imdb_subwords.csv\").query(\"split == '{}'\".format(mode)) # 加载训练集或测试集，query语句筛选\n",
    "        self.texts = df[\"subwords10k\"].values # 评论文本\n",
    "        self.labels = df[\"label\"].values # 评论标签\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self.labels)\n",
    "    \n",
    "    def __getitem__(self, idx):\n",
    "        return self.texts[idx].split(), self.labels[idx] # 返回文本和标签\n",
    "    \n",
    "    \n",
    "train_ds = IMDBDataset(\"train\")\n",
    "test_ds = IMDBDataset(\"test\")"
   ],
   "outputs": [],
   "execution_count": 9
  },
  {
   "cell_type": "code",
   "source": [
    "train_ds[0]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:22.813726Z",
     "start_time": "2025-03-10T16:24:22.804732Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(['i',\n",
       "  'really',\n",
       "  'liked',\n",
       "  'sum@@',\n",
       "  'mer@@',\n",
       "  'sla@@',\n",
       "  'm',\n",
       "  'due',\n",
       "  'look',\n",
       "  'a@@',\n",
       "  'ren@@',\n",
       "  'a',\n",
       "  ',',\n",
       "  'cur@@',\n",
       "  'tain',\n",
       "  'look',\n",
       "  'overall',\n",
       "  'interesting',\n",
       "  'reason',\n",
       "  '.',\n",
       "  'anyways',\n",
       "  ',',\n",
       "  'could',\n",
       "  'one',\n",
       "  'best',\n",
       "  'sum@@',\n",
       "  'mer@@',\n",
       "  'sla@@',\n",
       "  'm',\n",
       "  'ever',\n",
       "  'w@@',\n",
       "  'w@@',\n",
       "  'f',\n",
       "  'le@@',\n",
       "  'x',\n",
       "  'lu@@',\n",
       "  'ger',\n",
       "  'main',\n",
       "  'event',\n",
       "  'yo@@',\n",
       "  'ko@@',\n",
       "  'z@@',\n",
       "  'un@@',\n",
       "  'a',\n",
       "  ',',\n",
       "  'time',\n",
       "  'ok',\n",
       "  'huge',\n",
       "  'fat',\n",
       "  'man',\n",
       "  'v',\n",
       "  'strong',\n",
       "  'man',\n",
       "  'i',\n",
       "  'glad',\n",
       "  'time',\n",
       "  'changed',\n",
       "  '.',\n",
       "  'it',\n",
       "  'terrible',\n",
       "  'main',\n",
       "  'event',\n",
       "  'like',\n",
       "  'every',\n",
       "  'match',\n",
       "  'lu@@',\n",
       "  'ger',\n",
       "  'terrible',\n",
       "  '.',\n",
       "  'other',\n",
       "  'match',\n",
       "  'card',\n",
       "  'ra@@',\n",
       "  'z@@',\n",
       "  'or',\n",
       "  'ra@@',\n",
       "  'mon',\n",
       "  'v',\n",
       "  'ted',\n",
       "  'di@@',\n",
       "  'bi@@',\n",
       "  'ase',\n",
       "  ',',\n",
       "  'ste@@',\n",
       "  'in@@',\n",
       "  'er',\n",
       "  'brothers',\n",
       "  'v',\n",
       "  'hea@@',\n",
       "  'ven@@',\n",
       "  'ly',\n",
       "  'bo@@',\n",
       "  'dies',\n",
       "  ',',\n",
       "  'sha@@',\n",
       "  'wn',\n",
       "  'micha@@',\n",
       "  'els',\n",
       "  'v',\n",
       "  'cur@@',\n",
       "  't',\n",
       "  'h@@',\n",
       "  'ening',\n",
       "  ',',\n",
       "  'event',\n",
       "  'sha@@',\n",
       "  'wn',\n",
       "  'named',\n",
       "  'big',\n",
       "  'monster',\n",
       "  'body',\n",
       "  'guard',\n",
       "  'die@@',\n",
       "  'sel',\n",
       "  ',',\n",
       "  'irs',\n",
       "  'v',\n",
       "  '-',\n",
       "  '-',\n",
       "  'kid',\n",
       "  ',',\n",
       "  'bre@@',\n",
       "  't',\n",
       "  'hart',\n",
       "  'first',\n",
       "  'take',\n",
       "  'do@@',\n",
       "  'ink',\n",
       "  'take',\n",
       "  'jerry',\n",
       "  'law@@',\n",
       "  'ler',\n",
       "  'stuff',\n",
       "  'har@@',\n",
       "  'ts',\n",
       "  'law@@',\n",
       "  'ler',\n",
       "  'always',\n",
       "  'interesting',\n",
       "  ',',\n",
       "  'lu@@',\n",
       "  'd@@',\n",
       "  'vi@@',\n",
       "  'g',\n",
       "  'bor@@',\n",
       "  'ga',\n",
       "  'destroyed',\n",
       "  'marty',\n",
       "  'jan@@',\n",
       "  'ne@@',\n",
       "  'tty',\n",
       "  ',',\n",
       "  'under@@',\n",
       "  'taker',\n",
       "  'took',\n",
       "  'giant',\n",
       "  'gon@@',\n",
       "  'z@@',\n",
       "  'ale@@',\n",
       "  'z',\n",
       "  'another',\n",
       "  'terrible',\n",
       "  'match',\n",
       "  ',',\n",
       "  'the',\n",
       "  'smoking',\n",
       "  'g@@',\n",
       "  'unn@@',\n",
       "  's',\n",
       "  'tat@@',\n",
       "  'an@@',\n",
       "  'ka',\n",
       "  'took',\n",
       "  'ba@@',\n",
       "  'm',\n",
       "  'ba@@',\n",
       "  'm',\n",
       "  'bi@@',\n",
       "  'ge@@',\n",
       "  'low',\n",
       "  'head@@',\n",
       "  'shr@@',\n",
       "  'in@@',\n",
       "  'kers',\n",
       "  ',',\n",
       "  'yo@@',\n",
       "  'ko@@',\n",
       "  'z@@',\n",
       "  'un@@',\n",
       "  'a',\n",
       "  'def@@',\n",
       "  'ended',\n",
       "  'world',\n",
       "  'title',\n",
       "  'le@@',\n",
       "  'x',\n",
       "  'lu@@',\n",
       "  'ger',\n",
       "  'match',\n",
       "  'boring',\n",
       "  'terrible',\n",
       "  'ending',\n",
       "  '.',\n",
       "  'however',\n",
       "  'deserves'],\n",
       " np.int64(1))"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 构造 word2idx 和 idx2word"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:22.820609Z",
     "start_time": "2025-03-10T16:24:22.814717Z"
    }
   },
   "source": [
    "#载入词表，看下词表长度，词表就像英语字典\n",
    "word2idx = {\n",
    "    \"[PAD]\": 0,     # 填充 token\n",
    "    \"[BOS]\": 1,     # begin of sentence\n",
    "    \"[UNK]\": 2,     # 未知 token\n",
    "    \"[EOS]\": 3,     # end of sentence\n",
    "}\n",
    "idx2word = {value: key for key, value in word2idx.items()}\n",
    "print(idx2word)\n",
    "index = len(idx2word) # 词表长度，现在为4\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{0: '[PAD]', 1: '[BOS]', 2: '[UNK]', 3: '[EOS]'}\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": [
    "threshold = 1  # 出现次数低于此的token舍弃\n",
    "with open(\"imdb_bpe_vocab\", \"r\", encoding=\"utf8\") as file:\n",
    "    for line in tqdm(file.readlines()):\n",
    "        token, counts = line.strip().split()\n",
    "        if int(counts) >= threshold:\n",
    "            word2idx[token] = index # 加入词表\n",
    "            idx2word[index] = token # 加入反向词典\n",
    "            index += 1\n",
    "\n",
    "vocab_size = len(word2idx)\n",
    "print(\"vocab_size: {}\".format(vocab_size))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:22.864448Z",
     "start_time": "2025-03-10T16:24:22.821598Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/8031 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "54a98d75b1fe49549761a22fae137a19"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "vocab_size: 8035\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.371097Z",
     "start_time": "2025-03-10T16:24:22.867451Z"
    }
   },
   "source": [
    "# 选择 max_length\n",
    "length_collect = {}\n",
    "for text, label in train_ds:\n",
    "    length = len(text)\n",
    "    length_collect[length] = length_collect.get(length, 0) + 1\n",
    "    \n",
    "MAX_LENGTH = 500\n",
    "plt.bar(length_collect.keys(), length_collect.values())\n",
    "plt.axvline(MAX_LENGTH, label=\"max length\", c=\"gray\", ls=\":\")\n",
    "plt.legend()\n",
    "plt.show()"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGdCAYAAAA44ojeAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAANshJREFUeJzt3Xl8VNX9//H3bAmJZjFAtkoIArIoi0YNcUFaUgPigqAVpQhKwQWsSqWIvypov98vVC3UWkRbFagiuFShxe3BjksAoaDggkCjYEkChSYBkWSW8/uj39yvIwmTwIS5yX09H495cObeM3c+h5vcfOacc8+4jDFGAAAANuKOdQAAAADfR4ICAABshwQFAADYDgkKAACwHRIUAABgOyQoAADAdkhQAACA7ZCgAAAA2/HGOoDjEQqFtGfPHiUlJcnlcsU6HAAA0ADGGB08eFDZ2dlyu4/dR9IsE5Q9e/aoXbt2sQ4DAAAch927d+v0008/Zp1mmaAkJSVJ+k8Dk5OTYxwNAABoiKqqKrVr1876O34szTJBqR3WSU5OJkFBowSDQa1du1aS1KdPH3k8nhhHBADO05DpGc0yQQGOVzAY1LJlyyRJ559/PgkKANgUCQocxe12q1evXlYZAGBPJChwFK/Xq8GDB8c6DABABCQoAICoM8YoEAgoGAzGOhScRB6PR16vNypLgJCgAACiqqamRqWlpTp8+HCsQ0EMJCYmKisrS3FxcSd0HBIUOEpNTY1mzJghSZowYcIJ/wIBCBcKhVRSUiKPx6Ps7GzFxcWxoKZDGGNUU1Ojffv2qaSkRJ07dz6huX4kKHCc6urqWIcAtFg1NTUKhUJq166dEhMTYx0OTrKEhAT5fD599dVXqqmpUatWrY77WCQocBSfz6fx48dbZQBNg7vknCta554EBY7icrnUunXrWIcBAIiAFBcAAJtxuVxatGhRrMOQJE2dOlW9e/c+6e9LggJHCQaDWr9+vdavX8/tjwDwPXZKjBjigaMEg0G99dZbkqTevXuz1D0A2BQ9KHAUt9ut7t27q3v37kziAxCmX79+uvPOO3X33XfrtNNOU0ZGhv70pz/pm2++0c0336ykpCR16tTJ+pAj/edDz+jRo9WhQwclJCSoS5cuevzxx639R44c0VlnnaWxY8da23bu3KmkpCQ999xzDY5t9+7d+slPfqLU1FSlpaXp6quv1pdffmntHzVqlAYPHqzHHntMWVlZat26tcaNGye/32/VKS0t1aBBg5SQkKAOHTroxRdfVG5urn73u99JknJzcyVJ11xzjVwul/W81vPPP6/c3FylpKRo2LBhOnjwYIPjPx5coeEoXq9X1113na677jp5vXQgAidTTU2NampqZIyxtgWDQdXU1CgQCES17vGaN2+e2rRpo/Xr1+vOO+/U7bffruuuu04XXnih/v73v+uyyy7TiBEjrEXoQqGQTj/9dL3yyiv69NNP9eCDD+r+++/Xyy+/LElq1aqV5s+fr3nz5mnx4sUKBoP66U9/qh//+Me65ZZbGhST3+9XUVGRkpKS9O677+r999/XqaeeqgEDBqimpsaqt3LlSu3cuVMrV67UvHnzNHfuXM2dO9faf9NNN2nPnj1atWqV/vKXv+iPf/yj9u7da+3/8MMPJUlz5sxRaWmp9Vz6T1K1aNEiLVmyREuWLNHq1as1ffr04/5/bhDTDFVWVhpJprKyMtahAAC+49tvvzWffvqp+fbbb4/aN3XqVDN16lRz6NAha9vq1avN1KlTzeLFi8Pq/vd//7eZOnWq+fe//21tKy4uNlOnTjV/+ctfwuo+8sgjZurUqaa8vPyEYr/00kvNxRdfbD0PBALmlFNOMSNGjLC2lZaWGkmmuLi43uOMGzfODB069KgY27RpY8aPH2+ysrLMv/71r2PGIsm8/vrrxhhjnn/+edOlSxcTCoWs/dXV1SYhIcG88847xhhjRo4cadq3b28CgYBV57rrrjPXX3+9McaYzz77zEgyH374obV/+/btRpKZOXNmne9ba8qUKSYxMdFUVVVZ2yZOnGjy8/PrjP1YPwON+fvNR0gAAP5Xz549rbLH41Hr1q3Vo0cPa1tGRoYkhfU8zJo1S88995x27dqlb7/9VjU1NUfd9fKLX/xCixYt0h/+8Ae99dZbjVru4KOPPtKOHTuUlJQUtv3IkSPauXOn9fyss84Km1eXlZWlLVu2SJK2bdsmr9erc88919rfqVMnnXbaaQ2KITc3N+z9s7Kywv4PmgIJChzF7/friSeekCTdeeedLNYGnESTJ0+WFL5I4kUXXaQ+ffocNSfs3nvvParu+eefr3PPPfeounfddddRdY/X94/hcrnCttUu2x8KhSRJCxcu1L333qvf/va3KigoUFJSkh59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kszrr78etn/69OkmJSXFLFq0yHz00UfmqquuMh06dDDffvutVWfAgAGmV69eZu3atebdd981nTp1MjfccIO1v7Ky0mRkZJjhw4ebrVu3mgULFpiEhATz9NNPn6xmHuVY7a6oqDCFhYXmpZdeMp9//rkpLi42F1xwgcnLyws7Rvv27c3DDz8c9jPw3WuB3dod6VyPHDnSDBgwIKw9Bw4cCKvT0s61MSasvaWlpea5554zLpfL7Ny506rT3M51JCQoxpgLLrjAjBs3znoeDAZNdna2mTZtWgyjip69e/caSWb16tXWtksvvdTcdddd9b7mzTffNG6325SVlVnbZs+ebZKTk011dXVThntcpkyZYnr16lXnvoqKCuPz+cwrr7xibfvss8+MJFNcXGyMaX7trc9dd91lOnbsaEKhkDGm5Z1nY8xRF+9QKGQyMzPNo48+am2rqKgw8fHxZsGCBcYYYz799FMjyXz44YdWnbfeesu4XC7zz3/+0xhjzJNPPmlOO+20sHZPmjTJdOnSpYlb1DB1/dH6vvXr1xtJ5quvvrK2tW/f3sycObPe19i53fUlKFdffXW9r3HKub766qvNj370o7Btzflc18XxQzw1NTXauHGjCgsLrW1ut1uFhYUqLi6OYWTRU1lZKUlKS0sL2z5//ny1adNGZ599tiZPnqzDhw9b+4qLi9WjR4+whfOKiopUVVWlTz755OQE3kjbt29Xdna2zjjjDA0fPly7du2SJG3cuFF+vz/sHHft2lU5OTnWOW6O7f2+mpoavfDCC7rlllvCvkSzpZ3n7yspKVFZWVnY+U1JSVF+fn7Y+U1NTdV5551n1SksLJTb7da6deusOn379lVcXJxVp6ioSNu2bdO///3vk9SaE1NZWSmXy3XUd5VNnz5drVu31jnnnKNHH300bAivObZ71apVSk9PV5cuXXT77bdr//791j4nnOvy8nK98cYbGj169FH7WtK5bhbfZtyU/vWvfykYDB61gm1GRoY+//zzGEUVPaFQSHfffbcuuuginX322db2G2+8Ue3bt1d2drY+/vhjTZo0Sdu2bdNrr70mSSorK6vz/6R2n93k5+dr7ty56tKli0pLS/XQQw/pkksu0datW1VWVqa4uLijLtoZGRlWW5pbe+uyaNEiVVRUaNSoUda2lnae61IbZ13t+O75TU9PD9vv9XqV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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 13
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tokenizer"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.386190Z",
     "start_time": "2025-03-10T16:24:24.373087Z"
    }
   },
   "source": [
    "class Tokenizer:\n",
    "    def __init__(self, word2idx, idx2word, max_length=500, pad_idx=0, bos_idx=1, eos_idx=3, unk_idx=2):\n",
    "        self.word2idx = word2idx\n",
    "        self.idx2word = idx2word\n",
    "        self.max_length = max_length\n",
    "        self.pad_idx = pad_idx\n",
    "        self.bos_idx = bos_idx\n",
    "        self.eos_idx = eos_idx\n",
    "        self.unk_idx = unk_idx\n",
    "    \n",
    "    def encode(self, text_list, padding_first=False):\n",
    "        \"\"\"如果padding_first == True，则padding加载前面，否则加载后面\"\"\"\n",
    "        max_length = min(self.max_length, 2 + max([len(text) for text in text_list]))\n",
    "        indices_list = []\n",
    "        for text in text_list:\n",
    "            indices = [self.bos_idx] + [self.word2idx.get(word, self.unk_idx) for word in text[:max_length-2]] + [self.eos_idx] #变为id，未登录词用unk_idx代替，句子前后加bos和eos\n",
    "            if padding_first: # padding加载前面\n",
    "                indices = [self.pad_idx] * (max_length - len(indices)) + indices\n",
    "            else:# padding加载后面\n",
    "                indices = indices + [self.pad_idx] * (max_length - len(indices))\n",
    "            indices_list.append(indices)\n",
    "        return torch.tensor(indices_list)\n",
    "    \n",
    "    \n",
    "    def decode(self, indices_list, remove_bos=True, remove_eos=True, remove_pad=True, split=False):\n",
    "        text_list = []\n",
    "        for indices in indices_list:\n",
    "            text = []\n",
    "            for index in indices:\n",
    "                word = self.idx2word.get(index, \"[UNK]\")\n",
    "                if remove_bos and word == \"[BOS]\":\n",
    "                    continue\n",
    "                if remove_eos and word == \"[EOS]\":\n",
    "                    break\n",
    "                if remove_pad and word == \"[PAD]\":\n",
    "                    break\n",
    "                text.append(word)\n",
    "            text_list.append(\" \".join(text) if not split else text)\n",
    "        return text_list\n",
    "    \n",
    "\n",
    "tokenizer = Tokenizer(word2idx=word2idx, idx2word=idx2word)\n",
    "raw_text = [\"hello world\".split(), \"i really liked sum@@ mer@@ sla@@ m due look a@@ ren@@ a , cur@@ \".split(), \"this is a test\".split()]\n",
    "indices = tokenizer.encode(raw_text, padding_first=False)\n",
    "\n",
    "print(\"raw text-------------------\")\n",
    "for raw in raw_text:\n",
    "    print(raw)\n",
    "print(\"indices---------------\")\n",
    "for index in indices:\n",
    "    print(index)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "raw text-------------------\n",
      "['hello', 'world']\n",
      "['i', 'really', 'liked', 'sum@@', 'mer@@', 'sla@@', 'm', 'due', 'look', 'a@@', 'ren@@', 'a', ',', 'cur@@']\n",
      "['this', 'is', 'a', 'test']\n",
      "indices---------------\n",
      "tensor([   1, 6513,  125,    3,    0,    0,    0,    0,    0,    0,    0,    0,\n",
      "           0,    0,    0,    0])\n",
      "tensor([   1,    6,   27,  514, 2230,  775, 1527,  146,  893,   65,   98,  666,\n",
      "          26,    5, 1571,    3])\n",
      "tensor([   1,   18,  395,   26, 1892,    3,    0,    0,    0,    0,    0,    0,\n",
      "           0,    0,    0,    0])\n"
     ]
    }
   ],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.390899Z",
     "start_time": "2025-03-10T16:24:24.387181Z"
    }
   },
   "cell_type": "code",
   "source": "idx2word[2230]",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'sum@@'"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 15
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.396650Z",
     "start_time": "2025-03-10T16:24:24.391821Z"
    }
   },
   "cell_type": "code",
   "source": [
    "decode_text = tokenizer.decode(indices.tolist(), remove_bos=False, remove_eos=False, remove_pad=False)\n",
    "print(\"decode text\")\n",
    "for decode in decode_text:\n",
    "    print(decode)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "decode text\n",
      "[BOS] hello world [EOS] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]\n",
      "[BOS] i really liked sum@@ mer@@ sla@@ m due look a@@ ren@@ a , cur@@ [EOS]\n",
      "[BOS] this is a test [EOS] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD] [PAD]\n"
     ]
    }
   ],
   "execution_count": 16
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.402632Z",
     "start_time": "2025-03-10T16:24:24.397646Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import re\n",
    "\n",
    "# 输入字符串\n",
    "text = \"i really liked sum@@ mer@@ sla@@ m due look a@@ ren@@ a , cur@@ \"\n",
    "\n",
    "# 使用正则表达式替换 \"@@ \" 为空字符串\n",
    "cleaned_text = re.sub(r'@@\\s*', '', text)\n",
    "\n",
    "print(cleaned_text)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i really liked summerslam due look arena , cur\n"
     ]
    }
   ],
   "execution_count": 17
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.410177Z",
     "start_time": "2025-03-10T16:24:24.403629Z"
    }
   },
   "source": [
    "def collate_fct(batch):\n",
    "    \"\"\"\n",
    "    把字符串列表转化为tensor\n",
    "    :param batch:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    text_list = [item[0] for item in batch] #batch中每个item的第一个元素是text,是输入，类型为list\n",
    "    label_list = [item[1] for item in batch] #batch中每个item的第二个元素是label,是输出，类型为int\n",
    "    # 这里使用 padding first\n",
    "    text_list = tokenizer.encode(text_list, padding_first=True).to(dtype=torch.int)\n",
    "    return text_list, torch.tensor(label_list).reshape(-1, 1).to(dtype=torch.float)\n",
    "\n",
    "batch_size = 128\n",
    "train_dl = DataLoader(train_ds, batch_size=batch_size, shuffle=True, collate_fn=collate_fct)\n",
    "test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, collate_fn=collate_fct)"
   ],
   "outputs": [],
   "execution_count": 18
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.429078Z",
     "start_time": "2025-03-10T16:24:24.411171Z"
    }
   },
   "source": [
    "class LSTM(nn.Module):\n",
    "    def __init__(self, embedding_dim=16, hidden_dim=64, vocab_size=vocab_size, num_layers=1, bidirectional=False):\n",
    "        super(LSTM, self).__init__()\n",
    "        self.embeding = nn.Embedding(vocab_size, embedding_dim)\n",
    "        self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers=num_layers, batch_first=True, bidirectional=bidirectional)\n",
    "        self.layer = nn.Linear(hidden_dim * (2 if bidirectional else 1), hidden_dim)\n",
    "        self.fc = nn.Linear(hidden_dim, 1)\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # [bs, seq length]\n",
    "        x = self.embeding(x)\n",
    "        # [bs, seq length, embedding_dim] -> shape [bs, seq length, hidden_dim ]\n",
    "        seq_output, (hidden, cell) = self.lstm(x)\n",
    "\n",
    "        x = seq_output[:, -1, :]\n",
    "        # 取最后一个时间步的输出 (这也是为什么要设置padding_first=True的原因)\n",
    "        x = self.layer(x)\n",
    "        x = self.fc(x)\n",
    "        return x\n",
    "    \n",
    "sample_inputs = torch.randint(0, vocab_size, (2, 128))\n",
    "    \n",
    "print(\"{:=^80}\".format(\" 一层单向 LSTM \"))       \n",
    "for key, value in LSTM().named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")\n",
    "\n",
    "    \n",
    "print(\"{:=^80}\".format(\" 一层双向 LSTM \"))       \n",
    "for key, value in LSTM(bidirectional=True).named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")\n",
    "\n",
    "    \n",
    "print(\"{:=^80}\".format(\" 两层单向 LSTM \"))       \n",
    "for key, value in LSTM(num_layers=2).named_parameters():\n",
    "    print(f\"{key:^40}paramerters num: {np.prod(value.shape)}\")\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "================================== 一层单向 LSTM ===================================\n",
      "            embeding.weight             paramerters num: 128560\n",
      "           lstm.weight_ih_l0            paramerters num: 4096\n",
      "           lstm.weight_hh_l0            paramerters num: 16384\n",
      "            lstm.bias_ih_l0             paramerters num: 256\n",
      "            lstm.bias_hh_l0             paramerters num: 256\n",
      "              layer.weight              paramerters num: 4096\n",
      "               layer.bias               paramerters num: 64\n",
      "               fc.weight                paramerters num: 64\n",
      "                fc.bias                 paramerters num: 1\n",
      "================================== 一层双向 LSTM ===================================\n",
      "            embeding.weight             paramerters num: 128560\n",
      "           lstm.weight_ih_l0            paramerters num: 4096\n",
      "           lstm.weight_hh_l0            paramerters num: 16384\n",
      "            lstm.bias_ih_l0             paramerters num: 256\n",
      "            lstm.bias_hh_l0             paramerters num: 256\n",
      "       lstm.weight_ih_l0_reverse        paramerters num: 4096\n",
      "       lstm.weight_hh_l0_reverse        paramerters num: 16384\n",
      "        lstm.bias_ih_l0_reverse         paramerters num: 256\n",
      "        lstm.bias_hh_l0_reverse         paramerters num: 256\n",
      "              layer.weight              paramerters num: 8192\n",
      "               layer.bias               paramerters num: 64\n",
      "               fc.weight                paramerters num: 64\n",
      "                fc.bias                 paramerters num: 1\n",
      "================================== 两层单向 LSTM ===================================\n",
      "            embeding.weight             paramerters num: 128560\n",
      "           lstm.weight_ih_l0            paramerters num: 4096\n",
      "           lstm.weight_hh_l0            paramerters num: 16384\n",
      "            lstm.bias_ih_l0             paramerters num: 256\n",
      "            lstm.bias_hh_l0             paramerters num: 256\n",
      "           lstm.weight_ih_l1            paramerters num: 16384\n",
      "           lstm.weight_hh_l1            paramerters num: 16384\n",
      "            lstm.bias_ih_l1             paramerters num: 256\n",
      "            lstm.bias_hh_l1             paramerters num: 256\n",
      "              layer.weight              paramerters num: 4096\n",
      "               layer.bias               paramerters num: 64\n",
      "               fc.weight                paramerters num: 64\n",
      "                fc.bias                 paramerters num: 1\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:24.519295Z",
     "start_time": "2025-03-10T16:24:24.430072Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad()\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = []\n",
    "    pred_list = []\n",
    "    label_list = []\n",
    "    for datas, labels in dataloader:\n",
    "        datas = datas.to(device)\n",
    "        labels = labels.to(device)\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失\n",
    "        loss_list.append(loss.item())\n",
    "        # 二分类\n",
    "        preds = logits > 0\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list)\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 20
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### TensorBoard 可视化\n",
    "\n",
    "\n",
    "训练过程中可以使用如下命令启动tensorboard服务。\n",
    "\n",
    "```shell\n",
    "tensorboard \\\n",
    "    --logdir=runs \\     # log 存放路径\n",
    "    --host 0.0.0.0 \\    # ip\n",
    "    --port 8848         # 端口\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:29.180356Z",
     "start_time": "2025-03-10T16:24:24.521285Z"
    }
   },
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "\n",
    "\n",
    "class TensorBoardCallback:\n",
    "    def __init__(self, log_dir, flush_secs=10):\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            log_dir (str): dir to write log.\n",
    "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
    "        \"\"\"\n",
    "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
    "\n",
    "    def draw_model(self, model, input_shape):\n",
    "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
    "        \n",
    "    def add_loss_scalars(self, step, loss, val_loss):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/loss\", \n",
    "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
    "            global_step=step,\n",
    "            )\n",
    "        \n",
    "    def add_acc_scalars(self, step, acc, val_acc):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/accuracy\",\n",
    "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
    "            global_step=step,\n",
    "        )\n",
    "        \n",
    "    def add_lr_scalars(self, step, learning_rate):\n",
    "        self.writer.add_scalars(\n",
    "            main_tag=\"training/learning_rate\",\n",
    "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
    "            global_step=step,\n",
    "            \n",
    "        )\n",
    "    \n",
    "    def __call__(self, step, **kwargs):\n",
    "        # add loss\n",
    "        loss = kwargs.pop(\"loss\", None)\n",
    "        val_loss = kwargs.pop(\"val_loss\", None)\n",
    "        if loss is not None and val_loss is not None:\n",
    "            self.add_loss_scalars(step, loss, val_loss)\n",
    "        # add acc\n",
    "        acc = kwargs.pop(\"acc\", None)\n",
    "        val_acc = kwargs.pop(\"val_acc\", None)\n",
    "        if acc is not None and val_acc is not None:\n",
    "            self.add_acc_scalars(step, acc, val_acc)\n",
    "        # add lr\n",
    "        learning_rate = kwargs.pop(\"lr\", None)\n",
    "        if learning_rate is not None:\n",
    "            self.add_lr_scalars(step, learning_rate)\n"
   ],
   "outputs": [],
   "execution_count": 21
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save Best\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:29.187689Z",
     "start_time": "2025-03-10T16:24:29.181342Z"
    }
   },
   "source": [
    "class SaveCheckpointsCallback:\n",
    "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
    "        \"\"\"\n",
    "        Save checkpoints each save_epoch epoch. \n",
    "        We save checkpoint by epoch in this implementation.\n",
    "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
    "\n",
    "        Args:\n",
    "            save_dir (str): dir to save checkpoint\n",
    "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
    "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
    "        \"\"\"\n",
    "        self.save_dir = save_dir\n",
    "        self.save_step = save_step\n",
    "        self.save_best_only = save_best_only\n",
    "        self.best_metrics = -1\n",
    "        \n",
    "        # mkdir\n",
    "        if not os.path.exists(self.save_dir):\n",
    "            os.mkdir(self.save_dir)\n",
    "        \n",
    "    def __call__(self, step, state_dict, metric=None):\n",
    "        if step % self.save_step > 0:\n",
    "            return\n",
    "        \n",
    "        if self.save_best_only:\n",
    "            assert metric is not None\n",
    "            if metric >= self.best_metrics:\n",
    "                # save checkpoints\n",
    "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
    "                # update best metrics\n",
    "                self.best_metrics = metric\n",
    "        else:\n",
    "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
    "\n"
   ],
   "outputs": [],
   "execution_count": 22
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Early Stop"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:24:29.194769Z",
     "start_time": "2025-03-10T16:24:29.188684Z"
    }
   },
   "source": [
    "class EarlyStopCallback:\n",
    "    def __init__(self, patience=5, min_delta=0.01):\n",
    "        \"\"\"\n",
    "\n",
    "        Args:\n",
    "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
    "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute \n",
    "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
    "        \"\"\"\n",
    "        self.patience = patience\n",
    "        self.min_delta = min_delta\n",
    "        self.best_metric = -1\n",
    "        self.counter = 0\n",
    "        \n",
    "    def __call__(self, metric):\n",
    "        if metric >= self.best_metric + self.min_delta:\n",
    "            # update best metric\n",
    "            self.best_metric = metric\n",
    "            # reset counter \n",
    "            self.counter = 0\n",
    "        else: \n",
    "            self.counter += 1\n",
    "            \n",
    "    @property\n",
    "    def early_stop(self):\n",
    "        return self.counter >= self.patience\n"
   ],
   "outputs": [],
   "execution_count": 23
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:29:11.908836Z",
     "start_time": "2025-03-10T16:24:29.195766Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(\n",
    "    model, \n",
    "    train_loader, \n",
    "    val_loader, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=None,\n",
    "    save_ckpt_callback=None,\n",
    "    early_stop_callback=None,\n",
    "    eval_step=500,\n",
    "    ):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
    "        for epoch_id in range(epoch):\n",
    "            # training\n",
    "            for datas, labels in train_loader:\n",
    "                datas = datas.to(device)\n",
    "                labels = labels.to(device)\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等\n",
    "                optimizer.step()\n",
    "                preds = logits > 0\n",
    "            \n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())    \n",
    "                loss = loss.cpu().item()\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                })\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval()\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train()\n",
    "                    \n",
    "                    # 1. 使用 tensorboard 可视化\n",
    "                    if tensorboard_callback is not None:\n",
    "                        tensorboard_callback(\n",
    "                            global_step, \n",
    "                            loss=loss, val_loss=val_loss,\n",
    "                            acc=acc, val_acc=val_acc,\n",
    "                            lr=optimizer.param_groups[0][\"lr\"],\n",
    "                            )\n",
    "                \n",
    "                    # 2. 保存模型权重 save model checkpoint\n",
    "                    if save_ckpt_callback is not None:\n",
    "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
    "\n",
    "                    # 3. 早停 Early Stop\n",
    "                    if early_stop_callback is not None:\n",
    "                        early_stop_callback(val_acc)\n",
    "                        if early_stop_callback.early_stop:\n",
    "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
    "                            return record_dict\n",
    "                    \n",
    "                # udate step\n",
    "                global_step += 1\n",
    "                pbar.update(1)\n",
    "                pbar.set_postfix({\"epoch\": epoch_id})\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20\n",
    "\n",
    "model = LSTM()\n",
    "\n",
    "# 1. 定义损失函数 采用交叉熵损失 (但是二分类)\n",
    "loss_fct = F.binary_cross_entropy_with_logits\n",
    "# 2. 定义优化器 采用 adam\n",
    "# Optimizers specified in the torch.optim package\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
    "\n",
    "# 1. tensorboard 可视化\n",
    "if not os.path.exists(\"runs\"):\n",
    "    os.mkdir(\"runs\")\n",
    "tensorboard_callback = TensorBoardCallback(\"runs/imdb-lstm-subword\")\n",
    "# tensorboard_callback.draw_model(model, [1, MAX_LENGTH])\n",
    "# 2. save best\n",
    "if not os.path.exists(\"checkpoints\"):\n",
    "    os.makedirs(\"checkpoints\")\n",
    "save_ckpt_callback = SaveCheckpointsCallback(\"checkpoints/imdb-lstm-subword\", save_step=len(train_dl), save_best_only=True)\n",
    "# 3. early stop\n",
    "early_stop_callback = EarlyStopCallback(patience=10)\n",
    "\n",
    "model = model.to(device)\n",
    "record = training(\n",
    "    model, \n",
    "    train_dl, \n",
    "    test_dl, \n",
    "    epoch, \n",
    "    loss_fct, \n",
    "    optimizer, \n",
    "    tensorboard_callback=tensorboard_callback,\n",
    "    save_ckpt_callback=save_ckpt_callback,\n",
    "    early_stop_callback=early_stop_callback,\n",
    "    eval_step=len(train_dl)\n",
    "    )"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/3920 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "545a08da503742e5a64c238c08be1a48"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 24
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:29:12.166150Z",
     "start_time": "2025-03-10T16:29:11.909835Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=500):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns)\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):    \n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid()\n",
    "        axs[idx].legend()\n",
    "        # axs[idx].set_xticks(range(0, train_df.index[-1], 5000))\n",
    "        # axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, train_df.index[-1], 5000)))\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record, sample_step=10)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "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K0aMGMGIESO4/PLLSUpKonv37lxwwQV07dqV4cOHM2zYMK666irS09NjnoegbAj+jug/wxWRJlda4uH78eabbzJ16lT27dtHQUEBLpeLHj16AHD06FEOHTrEBRdcYLrumjVraNq0qV8ICQTVFWclXs/m6/a981hulRFDMf8Cjx8/nnfffZePPvqIzZs3c9ddd5GXl8eYMWMAuPHGGw0GCz7ef/99LrvsMn/BcUWxL9vLP11jUVSJqyzzOUdex89rDwHg8gZqHOQoaw4EAkEokiSRZLdW6F+i3UKS3Rp1vVBxBNfSPPjgg3z//fc8//zz/PXXX6xZs4auXbvicrkibic4kiJJUrkYIqSmprJq1Sq++OILGjVqxOOPP0737t05ffo0FouFOXPm8Ouvv9KpUydef/112rdvz+7du8t8HoLoMPuO+D7D5f1XFt+Ryv5+fPnllzz44IPceuutzJ49mzVr1jBmzBj//hITEyOuX9zrAkF1wemp+PpdH7mFgZrTHUdzK20esRKzGBo9ejT/+c9/ePzxx+nRowdr1qxh5syZflOFffv2kZmZaVhn69atLFiwgFtvvbVsZh0DGw5lsUptx3eyFt5/3vo+SYSGEPXCSCAQVF/sdjteb/F3zhYuXMjNN9/M5ZdfTteuXWnYsCF79uwp/wkW0bFjR3+9g35O7dq189c5WK1WhgwZwksvvcS6devYs2cPv//+O6BdZA4YMICnnnqK1atXY7fb+f777yts/oKqSbx+PxYuXEj//v25++676dmzJ23atGHnzp3+11NTU2nRogVz5841Xb9bt24cOHDAnxYrEFQmiqLy4swt/OOL1aw/kBV2zEsztzBr42EAflp7iNfnbi92206PwtGcQp78aSPbj+SU6byLI88ZEEPfrjrAkz9tJLsw/h1JS2SgMG7cuLBpccGN7QDat29vyCOsSDo0TOX+C9qwZufVDD+1jmbOwzxo/YqnPTcaxrkqUUkLBIKKo0WLFixdupQ9e/aQkpIS9q5027Zt+e677xg1ahSSJPHYY49VqI34//3f/3HWWWfxzDPPMHr0aBYvXswbb7zBW2+9BcAvv/zCrl27GDRoEOnp6cyYMQNFUWjfvj1Lly5l7ty5DBs2jPr167N06VKOHTtGx44dK2z+gqpJvH4/2rZty8cff8ysWbNo2bIln3zyCcuXL6dly5b+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r+bee+/ljz/+4IILLgDg5MmTzJw5kxkzZpCbm8vIkSN57rnncDgcfPzxx4waNYqtW7fSvHnzUs05Ly+P4cOH069fP5YvX87Ro0e57bbbGDduHB9++CEej4fLLruMsWPH8sUXX+ByuVi2bBlSkf3O9ddfT8+ePfnf//6HxWJhzZo12Gy2YvYqiBuCviOGz3B5E+V3pKK/H7Is89///peWLVuya9cu7r77bv71r3/x1ltvAbBmzRouuOACbrnlFl577TWsVit//PEHXq928TthwgTeffddnnvuOYYMGcKRI0fYsqXqCIGyZuKv2nt/+89dTLiwYyXPJjq2H83xP951PBdoAATXDBnF0IkgIZNvliZnEhnSNyYNK4aiTJNLS7AatpHv8oaNyK3er4l3nwnC3hNl3+PoqD8yJIWIIYA5m45it8phU+ZyCz1h7bmzCwNi6Nx29XB5FDKS7RzPdXLwdIHffEGSoFZi9OekLYdzUBQVWa58izkhhoLEUFaBm4me6zjfspoGJ3fCny9y1+GL2X40l5/GDaikWQoEgrIgPT2dCy+8kM8//9x/sffNN99Qt25dzjvvPGRZpnv37v7xzzzzDN9//z0//fQT48aNK9W+P//8cwoLC/n4449JTtYuTN944w1GjRrFiy++iM1mIysri4svvpjWrVsD0LFj4IJm3759/POf/6RDB80Ptm3b8EWqAkFJqOjvx/333+9/3KJFC5599lnuvPNOvxh66aWX6N27t/85QOfOnQHIycnhtdde47///S/XXHMNaWlptG3bloEDB5bkrQsqCX29j16sOA1ucsaL9OAoRmHUBgqB7WQXXfwHXwNGMhLQo48MBeasECpDjMIuGjODknAkR4sMWS0yCfbQWdROsmG3ymBuokeu0xO2R1B2UWQo0Wbho1v6GF67aeoyvxiqlWjDGiH6FIxXUckudFO7mDqjikCIoSDXjaM5TrJJ5nH3GN62v4q68DX2FtZlh9qClXtPVdIsBYI4x5ak3X2uIBRFITsnh7TUVGRbUkzrXn/99YwdO5a33noLh8PBZ599xt/+9jdkWSY3N5cnn3yS6dOnk5mZicfjoaCggH379pV6zps3b6Z79+5+IQQwYMAAFEVh69atDBo0iJtvvpnhw4czdOhQhgwZwjXXXEOjRo0AGD9+PLfddhuffPIJQ4YM4eqrr/aLJkEV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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 25
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-10T16:29:18.309043Z",
     "start_time": "2025-03-10T16:29:12.167149Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "# load checkpoints\n",
    "model.load_state_dict(torch.load(\"checkpoints/imdb-lstm-subword/best.ckpt\", map_location=\"cpu\"))\n",
    "\n",
    "model.eval()\n",
    "loss, acc = evaluating(model, test_dl, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.4150\n",
      "accuracy: 0.8624\n"
     ]
    }
   ],
   "execution_count": 26
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
